import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.Socket;
import java.util.LinkedList;
import java.util.Scanner;

class MDHandler extends Thread 
{ 
	private Socket clientSock;
    private MDServer chatServer;
    String username;
    private File uploadFile = null;
    MDHandler(Socket s, MDServer cs, String name) 
    {
        clientSock = s;   chatServer = cs; username = name;
    }
    
    public void sendShapeObjects(){
    	
    	ObjectOutputStream oos;
		try {
			oos = new ObjectOutputStream(clientSock.getOutputStream());
			oos.writeObject(chatServer.ShapeObjects);
		} catch (IOException e) {
			e.printStackTrace();
		}
    }
	public void run() 
    {
    	sendShapeObjects();
        try 
        {   
        	
        	Scanner in =
              new Scanner(clientSock.getInputStream());
            PrintWriter out = new PrintWriter(new OutputStreamWriter(clientSock.getOutputStream()),true);
            out.println("<<USRMSG>>>>>> Welcome to the MD Server <<<<\n");
            out.println("<<USRMSG>>Type \'bye\' to exit MD system.\n");
            chatServer.broadcast("<<USRMSG>>" + username + " has joined discussion.", "Chat Server");
            while (true) 	
            {
            	String message = in.nextLine().trim();
            	if (message.equals("bye")) 
                {
            	    chatServer.broadcast(username + " has left discussion.", "Chat Server");
            	    break;
                }else if(message.contains("<<REF>>")){
            		chatServer.broadcast("<<REFSHAPEOBJS>>", username);
            		chatServer.broadcastShapeObjects();
                }else if(message.contains("<<UPDATESHAPES>>")){
                	PrintWriter p = new PrintWriter(clientSock.getOutputStream(), true);
            	    p.println("<<READY>>");	
                	getShapeObjects();
                	p.println("<<GOTEM>>");
                }else if(message.contains("USRMSG")){
                	chatServer.broadcast(message,username);
                }else if(message.contains("<<GETALLFILENAMES>>")){
                	File dir = new File("Drawings");
                	String[] filenames = dir.list();
                	for(String s: filenames){
                		chatServer.broadcast("<<FILENAME>>"+ s,username);                		
                	}
                }else if(message.contains("<<NEWDRAWING>>")){
                	chatServer.ShapeObjects.clear();
                	PrintWriter p = new PrintWriter(clientSock.getOutputStream(), true);
                	p.println("<<GOTEM>>");
                	chatServer.setFileName("");
                }else if(message.contains("<<GETFILENAME>>")){ 
                	PrintWriter p = new PrintWriter(clientSock.getOutputStream(), true);
                	p.println("<<RETURNFILENAME>>"+chatServer.getFileName());
                }else if(message.contains("<<SAVEFILE>>")){ 
                	String fileName = message.replace("<<SAVEFILE>>", "Drawings/");
                	//code to save file 
                	ObjectOutputStream oos;
            		try{
            			oos = new ObjectOutputStream(new FileOutputStream(fileName));
            		    oos.writeObject(chatServer.ShapeObjects);
            		    oos.close();
            		    chatServer.setFileName(fileName);
            		    chatServer.broadcast("<<USRMSG>>Saved drawing as "
            		    		+fileName.replace("Drawings/", ""), username);
            		}catch(FileNotFoundException fnfe){
            			System.out.println("FileNotFoundException"); 
            		}catch(IOException ioe){
            			System.out.println("IOException");
            		}
                }else if(message.contains("<<DELETEFILE>>")){ 
                	String delFile = message.replace("<<DELETEFILE>>", "");
                	File file = new File(delFile);
                	if(file.delete()){
	                	if(delFile.equals(chatServer.getFileName())){
	                		chatServer.setFileName("");
	                		chatServer.ShapeObjects.clear();
	                	}
	                	chatServer.broadcast("<<USRMSG>>Deleted drawing "
            		    		+delFile.replace("Drawings/", ""), username);
	                	System.out.println("done deleting "+delFile);
                	}else{
                		System.out.println("ERROR deleting "+delFile);
                	}
                	PrintWriter p = new PrintWriter(clientSock.getOutputStream(), true);
                	p.println("<<GOTEM>>");
                }else if(message.contains("<<DOWNLOADFILE>>")){ 
                	PrintWriter p = new PrintWriter(clientSock.getOutputStream(), true);
                	p.println(message);
                }else if(message.contains("<<READYTODOWNLOADFILE>>")){ 
                	String downFile = message.replace("<<READYTODOWNLOADFILE>>", "");
                	File file = new File(downFile);
                	if(file != null){
	         			ObjectOutputStream oos;
	         			try {
	         				System.out.println("sending file");	         				
	         				oos = new ObjectOutputStream(clientSock.getOutputStream());
	         				oos.writeObject(file);
	         			} catch (IOException ioe) {
	         				ioe.printStackTrace();
	         			}
                	 }
                }else if(message.contains("<<OPENDRAWING>>")){
                	String fileName = message.replace("<<OPENDRAWING>>", "");
                	//code to replace ShapeObjects with file based on fileName
                	ObjectInputStream ois;
            	    Object ob = null;
            	    try{
            	        ois = new ObjectInputStream(new FileInputStream(fileName));
            	        ob = ois.readObject();
            	        chatServer.ShapeObjects = (LinkedList<ShapeObject>)ob;
            	        chatServer.setFileName(fileName.replace("Drawings/", ""));
            	    }catch(ClassCastException cce){
            	    	System.out.println("ClassCastException");
            	    }catch(ClassNotFoundException cnfe){
            	    	System.out.println("ClassNotFoundException");
            	    }catch(FileNotFoundException fnfe){
            	    	System.out.println("FileNotFoundException");
            	    }catch(IOException ioe){
            	    	System.out.println("IOException");
            	    }
                	PrintWriter p = new PrintWriter(clientSock.getOutputStream(), true);
                	p.println("<<GOTEM>>");
                }else if(message.contains("<<UPLOADFILE>>")){
                	String fn = message.replace("<<UPLOADFILE>>", "");
                	File dir = new File ("Drawings/");
            		String[] filenames = dir.list();
            		boolean duplicate = false;
                	for(String s: filenames){
                		if (s.equals(fn)){
                			duplicate = true;
                		}
                	}
                	PrintWriter p = new PrintWriter(clientSock.getOutputStream(), true);
                	if(duplicate){
	                	p.println("<<DUPLICATE>>"+fn);
	                	System.out.println("<<DUPLICATE>>"+fn);
                	}else{
	                	p.println("<<READYFORUPLOAD>>");
	                	ObjectInputStream ois = new ObjectInputStream(clientSock.getInputStream());
	                	try {
	                		File f = (File) ois.readObject();
	                		if(f.getName().endsWith(".ser")){
		                    	f.renameTo(new File("Drawings/" + f.getName()));
	                		}else if(f.getName().endsWith(".class")){
	                			f.renameTo(new File(f.getName()));
	                			chatServer.broadcast("<<SENDINGCLASSFILE>>"+f.getName(), username);
	                			chatServer.broadcastFile(f);
	                		}
						} catch (ClassNotFoundException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						} catch (SecurityException e) {
							e.printStackTrace();
						}
                	}	
            	}
            }
            chatServer.remove(clientSock);
            clientSock.close();
        }
        catch (IOException e) { System.out.println("Chat error: " + e); }
    }
    public boolean getShapeObjects(){
		   try {
			   ObjectInputStream ois = new ObjectInputStream(clientSock.getInputStream());
			   chatServer.refreshShapeObjects((LinkedList<ShapeObject>)ois.readObject());
		   } catch (IOException e) {
			   e.printStackTrace();
			   return false;
		   } catch (ClassNotFoundException e) {
			   e.printStackTrace();
			   return false;
		   }catch (Exception e){
			   e.printStackTrace();
			   return false;
		   }
		   return true;
	   }
}